环境声明:
go version go1.11
MongoDB server version 4.0.3
背景
这是我第一次接触golang和MongoDB,正在在参照他们的官方手册学习。想试着用“测试驱动开发”(TDD)的模式来做这个demo。
写这个demo的目的是为了让自己开始写一些golang的代码,和练习一下MongoDB简单的CRUD操作。
准备
数据结构
这个demo以对一个简单的通讯录进行插入、查询、更新、删除记录为例,collection中包含name和phone两个字段:
{ name : "Jack_Green", phone : "9987650" }
下载mgo
MongoDB还没出官方的golang驱动包,mgo是现在比较流行的第三方包,能找到的相关资料也比较多。
go get gopkg.in/mgo.v2
开始
参照MongoDB官方手册在本地搭了一套环境,练习了在mongo shell中使用命令的CRUD操作,熟悉了一下这个数据库。
准备实现对MongoDB的增、删、改、查操作,先想了下怎么写测试案例。测试用了比较简单的方法来实现,而且没有考虑可能出现的全部情况,而是只写了各个操作的某一种情况。
编写测试案例
文件名 gomd_test.go
可以自定义不同的db、collection名称,且测试时方便使对象统一修改,声明两个struct:
type Person struct {
Name string
Phone string
}
type Collection struct {
DB string
Name string
}
在测试代码文件中声明两个变量:
var col = Collection{"testDB", "contacts"}
var p = Person{"Jack_Green", "9987650"}
“C” 插入,测试插入方法,往通讯录中添加记录。不过要首先确保查询方法是可用的,我自己刚开始写的时候是先实现了查询方法,在插入之后,用查询方法把数据取出来打印。
// C create/insert
func TestInsert(t *testing.T) {
insert(p, col)
pb := findByName(p.Name, col)
if pb.Name != p.Name || pb.Phone != p.Phone {
t.Error("insert failed")
}
fmt.Println("Insert Result")
fmt.Println(pb)
}
“R” 查找,通过name查找该条记录。
// R read/find
func TestFindByName(t *testing.T) {
p := findByName(p.Name, col)
if p.Name == "" || p.Phone == "" {
t.Error("find by name test failed")
}
fmt.Println("Find Result")
fmt.Println(p)
}
“U” 更新,修改通讯录中某位的手机号,根据name修改phone
// U update
func TestUpdate(t *testing.T) {
p := Person{"WEW", "121212122"}
update(p, col)
ub := findByName(p.Name, col)
fmt.Println("Update Result")
fmt.Println(ub)
}
“D” 删除,根据name删除已存在的某条记录
// D delete
func TestDeleteData(t *testing.T) {
deleteData(p, col)
}
golang代码实现对MongoDB的CRUD
文件名 godm.go
刚刚开始写golang,对于创建session这部分有很多的冗余,等对它和mgo有了更深的了解之后,再来优化下。
导入必要的包
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
)
数据库地址
const (
URL = "127.0.0.1:27017"
)
往通讯录中添加一条记录
func insert(p Person, col Collection) {
session, err := mgo.Dial(URL)
if err != nil {
panic(err)
}
defer session.Close()
c := session.DB(col.DB).C(col.Name)
err = c.Insert(p)
if err != nil {
log.Fatal(err)
}
}
根据姓名从通讯录中查找联系方式
func findByName(name string, col Collection) Person {
session, err := mgo.Dial(URL)
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
collection := session.DB(col.DB).C(col.Name)
result := Person{}
err = collection.Find(bson.M{"name": name}).One(&result)
if err != nil {
log.Fatal(err)
}
return result
}
更新通讯录中某人的联系方式
func update(p Person, col Collection) {
session, err := mgo.Dial(URL)
if err != nil {
panic(err)
}
defer session.Close()
collection := session.DB(col.DB).C(col.Name)
err = collection.Update(bson.M{"name": p.Name}, bson.M{"$set": bson.M{"phone": p.Phone}})
if err != nil {
log.Fatal(err)
}
}
将某人的信息从通讯录中删除
func deleteData(p Person, col Collection) {
session, err := mgo.Dial(URL)
if err != nil {
panic(err)
}
defer session.Close()
collection := session.DB(col.DB).C(col.Name)
err = collection.Remove(bson.M{"name": p.Name})
}
测试结果
运行:
go test -v
输出:
=== RUN TestInsert
Insert Result
{Jack_Green 9987650}
--- PASS: TestInsert (0.03s)
=== RUN TestFindByName
Find Result
{Jack_Green 9987650}
--- PASS: TestFindByName (0.01s)
=== RUN TestUpdate
Update Result
{Jack_Green 121212122}
--- PASS: TestUpdate (0.02s)
=== RUN TestDeleteData
--- PASS: TestDeleteData (0.01s)
PASS
ok gomd 0.240s
附录
完整代码
Golang operation MongoDB demo : gomd
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。